package drds.global_transaction;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import drds.common.Author;
import drds.dbutils.native_sql.Db;
import drds.global_transaction.image.UndoLog;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;


@Author(name = Authors.LI_YANG)
@Slf4j
public class RollbackAndReleaseLocks
{
    /**
     * 单个数据库进行回滚,为一个分支事务,dubbo或者其他的rpc框架进行全局事务的传递,需要讨论一个分支事务是否支持其他的分支事务,eg远程RPC.
     */
    private void rollbackAndReleaseLock(TransactionId transactionId) throws SQLException
    {
        Connection connection = null;
        String globalTransactionId = transactionId.getGlobalTransactionId();
        String branchTransactionId = transactionId.getBranchTransactionId();
        String sql = "select id, undo_log from global_transaction_undo_log where branch_transaction_id = ? and global_transaction_id =?";

        Map<Long, String> map = new HashMap<>();
        ResultSet resultSet = Db.query(connection, sql, new Object[]{branchTransactionId, globalTransactionId});
        if (resultSet.next())
        {
            map.put(resultSet.getLong("id"), resultSet.getString("undo_log"));
        }
        if (map.size() > 0)
        {
            rollback(connection, map);
        }
        releaseLock(connection, transactionId);
    }

    private void rollback(Connection connection, Map<Long, String> map) throws SQLException
    {

        try
        {
            for (Long id : map.keySet())
            {
                String imageInfo = map.get(id);
                UndoLog undoLog = JSON.parseObject(imageInfo, new TypeReference<UndoLog>()
                {

                });
                undoLog.rollback();
                undoLog.setId(id);
                undoLog.updateStatusFinish(connection);
            }
        } catch (SQLException e)
        {
            log.error("SQLException.e", e);
            throw e;
        }
    }

    //branch_transaction_id branch_id
    public void releaseLock(Connection connection, TransactionId transactionId) throws SQLException
    {
        String globalTransactionId = transactionId.getGlobalTransactionId();
        String branchTransactionId = transactionId.getBranchTransactionId();
        String sql = "delete from global_transaction_lock where  branch_transaction_id=? and global_transaction_id =?";
        drds.dbutils.native_sql.Db.update(connection, sql, new Object[]{branchTransactionId, globalTransactionId});
        try
        {
            sql = "delete from global_transaction_undo_log where branch_transaction_id=? and global_transaction_id =? ";
            Db.update(connection, sql, new Object[]{branchTransactionId, globalTransactionId});
        } catch (SQLException e)
        {
            log.error("e", e);
        }
    }
}
